介紹
Electron 是可以做一個跨平台的桌面應用軟體。 Electron 是個用 JavaScrtip、HTML 及 CSS 等網頁技術開發原生應用程式的框架。因為 Electron的後端是使用node.js 前端是使用 javascript Html,用React 有模組化開發更方便。
實際上 Electron 他的後端有自己的node.js環境 ,我們只需要 靜態頁面的部分所以會使用next export來產生文件給 Electron 使用
安裝
省略...
"devDependencies"
"electron"
"electron-builder"
省略...
"dependencies"
"electron-is-dev": "0.3.0",
"electron-next": "3.0.8"
省略...
在 Electron 的entry有一個 node 跑 electron 透過 ipcMain與前端溝通,Electron的架構很簡單跟網頁一樣,並使用chromium 的方式執行
這邊的 prepareNext 使用 'electron-next'套件來把 Next export的靜態網頁 跑一個網頁或是靜態檔案給Electron可以正常使用
格式 可以指定 port
await prepareRenderer(< path >,< port >)
await prepareNext('./renderer')
發佈產品的話會使用 file ://協議 (next export 的靜態檔案)
開發模式,會起一個server來跑網頁模式這樣比較方便開發,
const url = isDev
? 'http://localhost:8000/start'
: format({
pathname: join(__dirname, '../renderer/start/index.html'),
protocol: 'file:',
slashes: true
})
// Native
const { join } = require('path')
const { format } = require('url')
// Packages
const { BrowserWindow, app, ipcMain } = require('electron')
const isDev = require('electron-is-dev')
const prepareNext = require('electron-next')
// Prepare the renderer once the app is ready
app.on('ready', async () => {
await prepareNext('./renderer')
const mainWindow = new BrowserWindow({
width: 800,
height: 600
})
const url = isDev
? 'http://localhost:8000/start'
: format({
pathname: join(__dirname, '../renderer/start/index.html'),
protocol: 'file:',
slashes: true
})
mainWindow.loadURL(url)
})
// 關閉事件
app.on('window-all-closed', app.quit)
// 透過ipcMain與前端溝通
ipcMain.on('message', (event, message) => {
event.sender.send('message', message)
})
前端部分 主要是載入 import { ipcRenderer } from 'electron' 要來跟 node ipcMan溝通
生命週期 起始的時候 componentDidMount 與結束的時候 做監聽與移除監聽
ipcRenderer.on('message', this.handleMessage)
ipcRenderer.removeListener('message', this.handleMessage)
之後透過 ipcRenderer.send('message', this.state.input) 的部分就可以跟node定義好的部分做溝通了
import { Component } from 'react'
import { ipcRenderer } from 'electron'
export default class extends Component {
state = {
input: '',
message: null
}
componentDidMount () {
// start listening the channel message
ipcRenderer.on('message', this.handleMessage)
}
componentWillUnmount () {
// stop listening the channel message
ipcRenderer.removeListener('message', this.handleMessage)
}
handleMessage = (event, message) => {
// receive a message from the main process and save it in the local state
this.setState({ message })
}
handleChange = event => {
this.setState({ input: event.target.value })
}
handleSubmit = event => {
event.preventDefault()
ipcRenderer.send('message', this.state.input)
this.setState({ message: null })
}
render () {
return (
<div>
<h1>Hello Electron!</h1>
{this.state.message &&
<p>{this.state.message}</p>
}
<form onSubmit={this.handleSubmit}>
<input type='text' onChange={this.handleChange} />
</form>
<style jsx>{`
h1 {
color: red;
font-size: 50px;
}
`}</style>
</div>
)
}
}
總結
Electron 中 只會使用到 Next.js 靜態網頁, 而Next.js的強項是 SSR Code splitting 還有一些代理webpack與File-system route,比較不太能感受 Next 的好處, 這樣的開發環境的優點是可以滿乾淨方便的 Route 使用filesystem 就搞定